@use 'constants';

.rd-diff-file-component {
  display: block;
  scroll-margin-top: var(--rd-app-sticky-top-with-padding);
  margin-bottom: var(--rd-diff-file-bottom-margin);
}

.rd-diff-file {
  $header-padding: constants.$diff-file-header-padding-y * 2;
  // top/bottom padding + toggle button size, excluding borders
  $file-header-height: calc($header-padding + $gl-button-small-size);
  --rd-diff-file-header-height: #{$file-header-height};
  --rd-diff-file-border-radius: #{$gl-border-radius-base};
  container: diff-file / normal;
}

.rd-diff-file-details > summary {
  display: none;
}

/*
  Rapid Diffs have 2 levels of rendering optimization using content-visibility:
    1. Coarse: the whole file is virtualized, skipping all of the rendering work.
       This is controlled through the --rd-content-visibility-auto property.
       --virtual-... configuration props allow to fine-tune the virtual dimensions of a diff file,
       which is done on a best effort approach.
    2. Fine-grained: each diff line is virtualized.
       This creates more layers on the GPU but still allows for performance gains.

  By default the Coarse method is used but Fine-grained can by applied when:
    1. The diff file is too large,
       then the Fine-grained mode is activated to improve page responsiveness for interactions with that file.
    1. Coarse mode is disabled and Fine-grained mode is activated to reduce the performance penalty.
       This can happen when we open a dropdown or add a diff discussion, which affects diff file dimensions.
       We need to disable content-visibility with opened dropdowns because it applies paint containment,
       which clips dropdowns content.
 */
.rd-diff-file[data-virtual],
.rd-diff-file[data-collapsed] {
  content-visibility: var(--rd-content-visibility-auto, auto);
}

.rd-diff-file[data-virtual] {
  // header top/bottom borders + body border
  contain-intrinsic-size:
    auto 0 auto
    calc(var(--rd-diff-file-header-height) + #{constants.$diff-file-border-width * 3} + var(--rd-body-intrinsic-height));

  @media (max-resolution: 1x) {
    // prevent pixel shifts on non-retina displays when hovering a line
    will-change: transform;
  }
}

.rd-diff-file[data-collapsed] {
  // header top/bottom borders only
  contain-intrinsic-size:
    auto 0 auto
    calc(var(--rd-diff-file-header-height) + #{constants.$diff-file-border-width * 2});
}

// content-visibility: auto; applies paint containment, which means you can not draw outside a diff file
// we need to disable this when we show dropdowns and other elements which extend past a diff file
.rd-diff-file[data-virtual]:has(button[aria-controls*='base-dropdown'][aria-expanded='true']),
// discussions change the dimensions of a diff file, virtual dimensions are no longer relevant,
// switch into Fine-grained mode
.rd-diff-file[data-virtual]:has([data-new-discussion-toggle]),
.rd-diff-file[data-virtual]:has([data-discussion-row]),
.rd-diff-file[data-virtual]:has(.zen-backdrop.fullscreen) {
  --rd-content-visibility-auto: visible;
}

.rd-diff-file-header-sticky {
  position: sticky;
  // 1px offset to hide top border
  top: calc(var(--rd-app-sticky-top, 1px) - 1px);
  z-index: constants.$diff-file-header-z-index;
  container-type: scroll-state;
}

.rd-diff-file-header-sticky:has([data-options-toggle] button[aria-expanded='true']) {
  z-index: constants.$diff-file-header-active-z-index;
}

.rd-diff-file-header {
  --rd-diff-file-header-horizontal-padding: #{$gl-spacing-scale-4};
  --rd-diff-file-header-vertical-padding: #{$gl-spacing-scale-3};
  @apply gl-text-default;
  display: flex;
  background-color: var(--gl-background-color-subtle);
  border: 1px solid var(--gl-border-color-default);
  padding: #{constants.$diff-file-header-padding-y} var(--rd-diff-file-header-horizontal-padding);
  border-radius: var(--rd-diff-file-border-radius) var(--rd-diff-file-border-radius) 0 0;
  word-break: break-word;

  @container scroll-state(stuck: top) {
    border-radius: 0 0 var(--rd-diff-file-border-radius) var(--rd-diff-file-border-radius);
  }
}

.rd-diff-file[data-collapsed] .rd-diff-file-header {
  border-radius: var(--rd-diff-file-border-radius);
}

.rd-diff-file-header-main {
  position: relative;
  // extra spacing to avoid accidental file collapse clicks
  padding: var(--rd-diff-file-header-vertical-padding);
  margin: calc(var(--rd-diff-file-header-vertical-padding) * -1);
  z-index: 1;
}

// we shouldn't use flex to align these items because it forces copy button to always wrap to a new line
.rd-diff-file-header-submodule,
.rd-diff-file-title,
.rd-diff-file-deleted {
  display: inline;
}

.rd-diff-file-title {
  @apply gl-text-default;
  font: inherit;
  font-weight: $gl-font-weight-heading;
  margin: 0;
}

.rd-diff-file-title .commit-sha {
  font-size: 85%;
  font-weight: normal;
}

.rd-diff-file-link {
  font: inherit;
  color: inherit;
}

.rd-diff-file-header-submodule,
.rd-diff-file-title,
.rd-file-mode-change,
.rd-copy-path,
.rd-diff-file-deleted,
.rd-submodule-icon.rd-submodule-icon {
  vertical-align: middle;
}

.rd-diff-file-title,
.rd-file-mode-change,
.rd-copy-path,
.rd-diff-file-deleted,
.rd-submodule-icon {
  margin-right: $gl-padding-4;
}

.rd-diff-file-moved {
  margin: 0 $gl-padding-4;
  font-weight: $gl-font-weight-normal;
}

.rd-diff-file-toggle {
  margin-right: $gl-spacing-scale-3;
}

.rd-diff-file[data-collapsed] .rd-diff-file-toggle-button[data-opened],
.rd-diff-file:not([data-collapsed]) .rd-diff-file-toggle-button[data-closed] {
  display: none;
}

.rd-diff-file-toggle-button::before {
  content: '';
  position: absolute;
  inset: 1px;
}

.rd-diff-file-info {
  $horizontal-padding: var(--rd-diff-file-header-horizontal-padding);
  $horizontal-padding-inv: calc(var(--rd-diff-file-header-horizontal-padding) * -1);
  $vertical-padding: var(--rd-diff-file-header-vertical-padding);
  $vertical-padding-inv: calc(var(--rd-diff-file-header-vertical-padding) * -1);
  position: relative;
  display: flex;
  align-self: flex-start;
  align-items: center;
  min-height: calc(#{$gl-button-small-size} + var(--rd-diff-file-header-vertical-padding) * 2);
  // extra spacing to avoid accidental file collapse clicks
  padding: $vertical-padding     $horizontal-padding     $vertical-padding     $vertical-padding;
  margin:  $vertical-padding-inv $horizontal-padding-inv $vertical-padding-inv auto;
  gap: $gl-padding;
  z-index: 1;
}

.rd-diff-file-stats {
  display: flex;
  align-items: center;
  margin: 0 0 0 auto;
  white-space: nowrap;
  gap: $gl-padding-8;
}

.rd-stats-added {
  @apply gl-text-success;
}

.rd-stats-removed {
  @apply gl-text-danger;
}

.rd-diff-file-body {
  --rd-content-border-radius: 0 0 var(--rd-diff-file-border-radius) var(--rd-diff-file-border-radius);
  --rd-content-border-color: var(--gl-border-color-default);
  border: constants.$diff-file-border-width solid var(--rd-content-border-color);
  border-top: 0;
  border-radius: var(--rd-content-border-radius);
}

@supports (content-visibility: hidden) {
  [data-file-body][hidden] {
    display: block !important;
    // https://web.dev/articles/content-visibility#hide_content_with_content-visibility_hidden
    // content-visibility: hidden preserves element's rendering state which improves performance for larger diffs
    content-visibility: hidden;
  }
}

